﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Web.Mvc;
using System.Linq;
using ElValWeb.ValidatorClientAdapters;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Configuration;

namespace ElValWeb {
    public class EntLibValidatorWrapper : ModelValidator {
     
        private readonly Validator _validator;

        public EntLibValidatorWrapper(ModelMetadata metadata, ControllerContext context, Validator validator)
            : base(metadata, context) {
            _validator = validator;
        }

        public override IEnumerable<ModelValidationResult> Validate(object container) {
            return ConvertResults(_validator.Validate(Metadata.Model));
        }

        public override IEnumerable<ModelClientValidationRule> GetClientValidationRules() {
            return GetValidationData();
        }

        private IEnumerable<ModelClientValidationRule> GetValidationData() {
            long ticks = DateTime.Now.Ticks;
            var validationSettings =
                ConfigurationManager.GetSection(ValidationSettings.SectionName) as ValidationSettings;
            if(validationSettings == null) {
                return new List<ModelClientValidationRule>(); 
            }
            var typeSection  = validationSettings.Types.Where(type => type.Name == Metadata.ContainerType.FullName).FirstOrDefault();
            if(typeSection ==null) {
                return new List<ModelClientValidationRule>(); 
            }
            var rulsetSection = typeSection.Rulesets.Get(typeSection.DefaultRuleset);
            if (rulsetSection == null) {
                return new List<ModelClientValidationRule>();
            }
            var validationDatas = new List<ValidatorData>();
            validationDatas.AddRange(rulsetSection.Properties.Where(p => p.Name == Metadata.PropertyName).SelectMany(p => p.Validators));
            validationDatas.AddRange(rulsetSection.Fields.Where(p => p.Name == Metadata.PropertyName).SelectMany(p => p.Validators));

            var a = validationDatas.SelectMany(v => ClientAdapterFactory.GetAdapter(v).GetClientRules(Metadata.ModelType)).ToArray();
            Debug.WriteLine(DateTime.Now.Ticks - ticks);
            return a;
           

        }

        private IEnumerable<ModelValidationResult> ConvertResults(IEnumerable<ValidationResult> validationResults) {
            if (validationResults != null) {
                foreach (ValidationResult validationResult in validationResults) {
                    if (validationResult.NestedValidationResults != null) {
                        foreach (ModelValidationResult result in ConvertResults(validationResult.NestedValidationResults)) {
                            yield return result;
                        }
                    }

                    yield return new ModelValidationResult {
                                                               Message = validationResult.Message,
                                                               MemberName = validationResult.Key
                                                           };
                }
            }
        }
    }
}